//
//  Data.cpp
//  chatv
//
//  Created by 云 浮 on 12-7-9.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#include "Data.h"

#include "Logic.h"

using namespace FreeNet ;

// test info.
//const char localhost[] = "127.0.0.1" ;
const char localhost[] = "192.168.203.144" ;
const int login_port = 10000 ;
const int lobby_port = 10100 ;
const int session_port = 20000 ;

void* parse(void* buff) ;
void* parse(void* buff)
{
    return 0 ;
}

void* login_recv(void* param)
{
    while (CData::Instance()->getLoginFlag())
    {
        ::printf("login_recv function \n") ;
        sleep(1) ;
    }

    destroyThread(param) ;
    return 0 ;
}

void* lobby_recv(void* param)
{
    while (CData::Instance()->getLobbyFlag())
    {
        ::printf("lobby_recv function \n") ;
        sleep(1) ;
    }

    destroyThread(param) ;
    return 0 ;
}

void* session_recv(void* param)
{
    char recvBuf[1024] ;
    int len = 0 ;
    while (CData::Instance()->getSessionFlag())
    {
        ::memset(recvBuf, 0, 1024) ;
        if (-1 == (len = (int)::recv(CData::Instance()->getSessionInfo().fd, recvBuf, 1024, 0)))
        {
            continue ;
        }
        int pushlen = pushData(CData::Instance()->getSessionMsgID(), recvBuf, len) ;
        void* p = popData(CData::Instance()->getSessionMsgID(), pushlen) ;
        ::printf("recv message: [%s]\n", p) ;
        delete p ;
        p = 0 ;
        sleep(1000) ;
    }

    destroyThread(param) ;
    return 0 ;
}

CData* CData::pData = 0 ;
CData* CData::Instance()
{
    if (0 == pData)
    {
        pData = new CData() ;
    }
    return pData ;
}

void CData::initData()
{
//    strcpy(loginInfo.ip, localhost) ;
//    loginInfo.port = login_port ;
//    loginInfo.mode = NET_TCP ;
//    loginInfo.fd = connectServer(loginInfo.ip, loginInfo.port, loginInfo.mode, 0) ;
//    assert(-1 != loginInfo.fd) ;
//    
//    lobbyMax = 1 ;
//    lobbyInfos = new sNetInfo[lobbyMax] ;
//    for (int i = 0; i < lobbyMax; ++i)
//    {
//        strcpy(lobbyInfos[i].ip, localhost) ;
//        lobbyInfos[i].port = lobby_port + i ;
//        lobbyInfos[i].mode = NET_TCP ;
//        lobbyInfos[i].fd = connectServer(lobbyInfos[i].ip, lobbyInfos[i].port, lobbyInfos[i].mode, 0) ;
//        assert(-1 != lobbyInfos[i].fd) ;
//    }

    strcpy(sessionInfo.ip, localhost) ;
    sessionInfo.port = session_port ;
    sessionInfo.mode = NET_UDP ;
    
    sessionMax = 1000 ;
    sessionCount = 0 ;
    sessionInfos = new sSessionInfo[sessionMax] ;
    for (int i = 0; i < sessionMax; ++i)
    {
        sessionInfos[i].fd = -1 ;
    }

#if defined (__LINUX__)
    assert(-1 < createEpollServer(sessionInfo.ip, sessionInfo.port, sessionInfo.mode, sessionMax, 0)) ;
#elif defined (__MACOSX__)
    assert(-1 < createPollServer(sessionInfo.ip, sessionInfo.port, sessionInfo.mode, sessionMax, 0)) ;
#endif

//    // create login thread.
//    loginFlag = true ;
//    loginMsgID = createQueue(8 * 1024) ; // 8 MB.
//    createThread(loginThread, login_recv, 0) ;
//
//    // create lobby thread.
//    lobbyFlag = true ;
//    lobbyMsgID = createQueue(8 * 1024) ; // 8 MB.
//    createThread(lobbyThread, lobby_recv, 0) ;

    // create session thread.
    sessionFlag = true ;
    sessionMsgID = createQueue(8 * 1024) ; // 8 MB.
    createThread(sessionThread, session_recv, 0) ;
}

CData::CData()
{
}

CData::~CData()
{
    loginFlag = lobbyFlag = sessionFlag = false ;

    delete [] lobbyInfos ;
    delete [] sessionInfos ;

    delete CData::pData ;
}

int CData::addSession(const int fd, const int uuid, const int lobbyID, const char* ip, const int port)
{
    assert(-1 < fd) ;
    for (int i = 0; i < sessionMax; ++i)
    {
        if (-1 == sessionInfos[i].fd)
        {
            sessionInfos[i].fd = fd ;
            sessionInfos[i].uuid = uuid ;
            sessionInfos[i].index = i ;
            sessionInfos[i].lobbyID = lobbyID ;
            strcpy(sessionInfos[i].ip, ip) ;
            sessionInfos[i].port = port ;
            ++sessionCount ;
            return sessionInfos[i].index ;
        }
    }
    return -1 ;
}

int CData::addSession(const sSessionInfo info)
{
    assert(-1 < info.fd) ;
    for (int i = 0; i < sessionMax; ++i)
    {
        if (-1 == sessionInfos[i].fd)
        {
            ::memcpy(&(sessionInfos[i]), &info, sizeof(sSessionInfo)) ;
            sessionInfos[i].index = i ;
            ++sessionCount ;
            return sessionInfos[i].index ;
        }
    }
    return -1 ;
}

int CData::clearSessions()
{
    int res = 0 ;
    for (int i = 0; i < sessionMax; ++i)
    {
        if (-1 == sessionInfos[i].fd)
        {
            continue ;
        }
        disconnectClient(sessionInfos[i].fd, 0) ;
        sessionInfos[i].fd = -1 ;
        --sessionCount ;
        ++res ;
    }
    assert(0 == sessionCount) ;
    return res ;
}

int CData::delSessionByFD(const int fd)
{
    assert(-1 < fd) ;
    int res = -1 ;
    for (int i = 0; i < sessionMax; ++i)
    {
        if (fd == sessionInfos[i].fd)
        {
            disconnectClient(sessionInfos[i].fd, 0) ;
            sessionInfos[i].fd = -1 ;
            res = sessionInfos[i].index ;
            --sessionCount ;
            break ;
        }
    }
    return res ;
}

int CData::delSessionByUUID(const int uuid)
{
    assert(-1 < uuid) ;
    int res = -1 ;
    for (int i = 0; i < sessionMax; ++i)
    {
        if (-1 == sessionInfos[i].fd)
        {
            continue ;
        }
        if (uuid != sessionInfos[i].uuid)
        {
            continue ;
        }

        disconnectClient(sessionInfos[i].fd, 0) ;
        sessionInfos[i].fd = -1 ;
        res = sessionInfos[i].index ;
        --sessionCount ;
        break ;
    }
    return res ;
}

int CData::delSessionByIndex(const int index)
{
    assert(-1 < index && index < sessionMax) ;
    if (-1 == sessionInfos[index].fd)
    {
        return -1 ;
    }

    disconnectClient(sessionInfos[index].fd, 0) ;
    sessionInfos[index].fd = -1 ;
    --sessionCount ;

    assert(sessionInfos[index].index == index) ;
    return index ;
}

int CData::delSessionByLobbyID(const int lobbyID)
{
    assert(-1 < lobbyID && lobbyID < lobbyMax) ;
    int res = 0 ;
    for (int i = 0; i < sessionMax; ++i)
    {
        if (-1 == sessionInfos[i].fd)
        {
            continue ;
        }
        if (lobbyID == sessionInfos[i].lobbyID)
        {
            disconnectClient(sessionInfos[i].fd, 0) ;
            sessionInfos[i].fd = -1 ;
            --sessionCount ;
            ++res ;
        }
    }
    return res ;
}

int CData::delSessionByIP(const char* ip)
{
    assert(0 != ip && 0 != strcmp("", ip)) ;
    int res = 0 ;
    for (int i = 0; i < sessionMax; ++i)
    {
        if (-1 == sessionInfos[i].fd)
        {
            continue ;
        }
        if (0 != strcmp(sessionInfos[i].ip, ip))
        {
            continue ;
        }

        disconnectClient(sessionInfos[i].fd, 0) ;
        sessionInfos[i].fd = -1 ;
        --sessionCount ;
        ++res ;
    }
    return res ;
}

int CData::delSessionByPort(const int port)
{
    assert(-1 < port) ;
    int res = 0 ;
    for (int i = 0; i < sessionMax; ++i)
    {
        if (-1 == sessionInfos[i].fd)
        {
            continue ;
        }
        if (port != sessionInfos[i].port)
        {
            continue ;
        }
        disconnectClient(sessionInfos[i].fd, 0) ;
        sessionInfos[i].fd = -1 ;
        --sessionCount ;
        ++res ;
    }
    return -1 ;
}

const sSessionInfo* CData::getSessionInfoByFD(const int fd) const
{
    assert(-1 < fd) ;
    for (int i = 0; i < sessionMax; ++i)
    {
        if (fd == sessionInfos[i].fd)
        {
            return &(sessionInfos[i]) ;
        }
    }
    return 0 ;
}

const sSessionInfo* CData::getSessionInfoByUUID(const int uuid) const
{
    assert(-1 < uuid) ;
    for (int i = 0; i < sessionMax; ++i)
    {
        if (-1 == sessionInfos[i].fd)
        {
            continue ;
        }
        if (uuid == sessionInfos[i].uuid)
        {
            return &(sessionInfos[i]) ;
        }
    }
    return 0 ;
}

const sSessionInfo* CData::getSessionInfoByIndex(const int index) const
{
    assert(-1 < index && index < sessionMax) ;
    if (-1 == sessionInfos[index].fd)
    {
        return 0 ;
    }
    assert(index == sessionInfos[index].index) ;
    return &(sessionInfos[index]) ;
}

int CData::sendToLogin(const void* data, const int len)
{
    assert(0 != data && 0 < len) ;
    return (0 < sendMessage(data, len, loginInfo.fd, 0)) ;
}

int CData::sendToLobby(const void* data, const int len, const int lobbyID)
{
    assert(0 != data && 0 < len) ;
    assert(-1 < lobbyID && lobbyID < lobbyMax) ;
    return (0 < sendMessage(data, len, lobbyInfos[lobbyID].fd, 0)) ;
}

int CData::sendToClient(const void* data, const int len, const int fd)
{
    assert(0 != data && 0 < len) ;
    assert(-1 < fd) ;
    const sSessionInfo* pClient = CData::Instance()->getSessionInfoByFD(fd) ;
    return (0 < sendMessageTo(pClient->ip, pClient->port, data, len, 0)) ;
}
























